"""
Utility functions for server management.
"""

import os
import signal
import tempfile
from pathlib import Path
from typing import Optional


def get_pid_file_path(port: int) -> Path:
    """Get the PID file path for a specific port."""
    return Path(tempfile.gettempdir()) / f"ccwork-server-{port}.pid"


def write_pid_file(port: int, pid: int) -> None:
    """Write the server PID to a file."""
    pid_file = get_pid_file_path(port)
    with open(pid_file, 'w') as f:
        f.write(str(pid))


def read_pid_file(port: int) -> Optional[int]:
    """Read the server PID from file."""
    pid_file = get_pid_file_path(port)
    if not pid_file.exists():
        return None
    
    try:
        with open(pid_file, 'r') as f:
            return int(f.read().strip())
    except (ValueError, OSError):
        return None


def remove_pid_file(port: int) -> None:
    """Remove the PID file."""
    pid_file = get_pid_file_path(port)
    if pid_file.exists():
        try:
            pid_file.unlink()
        except OSError:
            pass


def is_process_running(pid: int) -> bool:
    """Check if a process is running."""
    try:
        # Send signal 0 to check if process exists
        os.kill(pid, 0)
        return True
    except (OSError, ProcessLookupError):
        return False


def stop_server(port: int) -> bool:
    """Stop the server running on the specified port."""
    pid = read_pid_file(port)
    if pid is None:
        # No PID file found, check if port is actually in use
        if check_port_in_use("localhost", port):
            print(f"⚠️  Port {port} is in use but no PID file found. The server may not be a ccwork instance.")
        return False
    
    if not is_process_running(pid):
        # Process not running, clean up PID file
        remove_pid_file(port)
        print(f"🧹 Cleaned up stale PID file for port {port}")
        return False
    
    try:
        # Send SIGTERM for graceful shutdown
        os.kill(pid, signal.SIGTERM)
        
        # Wait a moment for graceful shutdown
        import time
        time.sleep(1)
        
        # Check if process is still running
        if is_process_running(pid):
            # If still running after 5 seconds, force kill
            time.sleep(4)
            if is_process_running(pid):
                os.kill(pid, signal.SIGKILL)
        
        # Clean up PID file
        remove_pid_file(port)
        return True
        
    except (OSError, ProcessLookupError):
        # Process already terminated
        remove_pid_file(port)
        return False


def check_port_in_use(host: str, port: int) -> bool:
    """Check if a port is already in use."""
    import socket
    
    # Try to bind to the port
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        try:
            # Set SO_REUSEADDR to avoid "Address already in use" from previous runs
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.bind((host, port))
            return False
        except OSError as e:
            # Check if it's actually in use or just a permission issue
            if e.errno == 98:  # Address already in use
                return True
            elif e.errno == 13:  # Permission denied - port might be restricted
                return True
            else:
                # Other errors - assume port is available
                return False